using System;

using Multiplicity.Runtime.Serialization.Binary;

namespace Multiplicity.Reflection {

    abstract class TypeElementBase {

        public static TypeElementBase Parse(MetadataParser parser) {

            SignatureElement element = (SignatureElement)parser.ReadByte();

            if (PrimitiveTypeElement.IsPrimitiveTypeElement(element)) {
                return new PrimitiveTypeElement(element);
            }
            else if (element == SignatureElement.Class) {
                return new TypeElement(parser);
            }

            Throw.ToDoException("chaha, nezname");
            return null;
        }
    }

    class TypeElement : TypeElementBase {

        public readonly uint TypeToken;

        public TypeElement(MetadataParser parser) {
            this.TypeToken = parser.ReadCompressedToken(CodedTokenFamilyType.TypeDefOrRef);
        }

        public override string ToString() {
            return string.Format("[Class Token=0x{0:x}]", TypeToken);
        }
    }

    class PrimitiveTypeElement : TypeElementBase {

        public readonly SignatureElement Element;

        public PrimitiveTypeElement(SignatureElement element) {
            Throw.ArgumentExceptionIf(!IsPrimitiveTypeElement(element), "Signature element {0} isn't a primitive type element", element);

            this.Element = element;
        }

        public override string ToString() {
            return Enum.GetName(Element.GetType(), Element);
        }

        public static bool IsPrimitiveTypeElement(SignatureElement element) {
            byte el = (byte)(element);

            return ((el >= (byte)(SignatureElement.Boolean)) && (el <= (byte)(SignatureElement.String))) ||
                   (el == (byte)(SignatureElement.Object));
        }
    }
}